package com.yaoxun.quartz.util;

import org.quartz.CronExpression;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;

import com.yaoxun.quartz.domain.entity.ScheduleJob;
import com.yaoxun.quartz.exception.QuartzPluginException;
import com.yaoxun.quartz.job.CronJob;

/**
 * 定时任务工具类
 * @author Loren
 *
 */
public class ScheduleUtils {

	private static final String JOB_NAME = "TASK_";
	
	/**
	 * 判断是否在scheduler中存在jobId
	 * @param scheduler
	 * @param jobId
	 * @return
	 */
	public static boolean existJobKey(Scheduler scheduler, Long jobId) {
		JobKey jobKey = getJobKey(jobId);
		try {
			return scheduler.checkExists(jobKey);
		} catch (SchedulerException e) {
			e.printStackTrace();
			throw new IllegalArgumentException(e);
		}
	}
	
	/**
	 * 判断cron表达式是否正确
	 * @param cronExpression
	 * @return
	 */
	public static boolean isValidExpression(String cronExpression) {
		return CronExpression.isValidExpression(cronExpression);
	}
	
	/**
	 * 创建定时任务
	 * @param scheduler
	 * @param scheduleJob
	 */
	public static void createScheduleJob(Scheduler scheduler, ScheduleJob scheduleJob) {
		try {
			//构建job信息
			JobDetail jobDetail = JobBuilder.newJob(CronJob.class).withIdentity(getJobKey(scheduleJob.getJobId())).build();
			//表达式调度构建器
			CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
						.withMisfireHandlingInstructionDoNothing();
			//按新的cronExpression表达式构建一个新的trigger
	        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getJobId())).withSchedule(cronScheduleBuilder).build();
	        //放入参数，运行时的方法可以获取
	        jobDetail.getJobDataMap().put(ScheduleJob.PARAMS_NAME, scheduleJob);
			scheduler.scheduleJob(jobDetail, trigger);
			//如果状态的停止则，停止
			if(isStopStatus(scheduleJob)) {
				pauseJob(scheduler, scheduleJob.getJobId());
			}
		} catch (SchedulerException e) {
			throw new QuartzPluginException("创建定时任务失败", e);
		}
	}
	
	/**
	 * 判断runStatus 是否停止状态
	 * @param scheduleJob
	 * @return
	 */
	private static boolean isStopStatus(ScheduleJob scheduleJob) {
		if(scheduleJob.getJobStatus() != null && scheduleJob.getJobStatus() == ScheduleJob.JOB_STATUS_STOP) {
			return true;
		}
		return false;
	}
	
	/**
	 * 更新定时任务
	 * @param scheduler
	 * @param scheduleJob
	 */
	public static void updateScheduleJob(Scheduler scheduler, ScheduleJob scheduleJob) {
		try {
			TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());
			//表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
            		.withMisfireHandlingInstructionDoNothing();
            CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());
            //按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            //参数
            trigger.getJobDataMap().put(ScheduleJob.PARAMS_NAME, scheduleJob);
            
            scheduler.rescheduleJob(triggerKey, trigger);
            //如果状态的停止则，停止
			if(isStopStatus(scheduleJob)) {
				pauseJob(scheduler, scheduleJob.getJobId());
			}
		} catch (Exception e) {
			throw new QuartzPluginException("更新定时任务失败", e);
		}
	}
	
	/**
	 * 获取JOB的表达式触发器
	 * @return
	 */
	public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
		try {
			return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
		} catch (SchedulerException e) {
			throw new QuartzPluginException("获取定时任务CronTrigger出现异常", e);
		}
	}
	
	
	/**
	 * 立即执行定时任务
	 * @param scheduler
	 * @param scheduleJob
	 */
	public static void run(Scheduler scheduler, ScheduleJob scheduleJob) {
		JobKey jobKey = getJobKey(scheduleJob.getJobId());
		JobDataMap data = new JobDataMap();
		data.put(ScheduleJob.PARAMS_NAME, scheduleJob.getParams());
		try {
			scheduler.triggerJob(jobKey, data);
		} catch (SchedulerException e) {
			throw new QuartzPluginException("立即执行定时任务失败", e);
		}
	}
		
	/**
	 * 暂停任务
	 * @param scheduler
	 * @param jobId
	 */
	public static void pauseJob(Scheduler scheduler, Long jobId) {
		JobKey jobKey = getJobKey(jobId);
		try {
			scheduler.pauseJob(jobKey);
		} catch (SchedulerException e) {
			throw new QuartzPluginException("暂停定时任务失败", e);
		}
	}
	
	/**
	 * 恢复任务
	 * @param scheduler
	 * @param jobId
	 */
	public static void resumeJob(Scheduler scheduler, Long jobId) {
		JobKey jobKey = getJobKey(jobId);
		try {
			scheduler.resumeJob(jobKey);
		} catch (SchedulerException e) {
			throw new QuartzPluginException("暂停定时任务失败", e);
		}
	}
	
	/**
	 * 删除任务
	 * @param scheduler
	 * @param jobId
	 */
	public static void deleteJob(Scheduler scheduler, Long jobId) {
		JobKey jobKey = getJobKey(jobId);
		try {
			scheduler.deleteJob(jobKey);
		} catch (SchedulerException e) {
			throw new QuartzPluginException("删除定时任务失败", e);
		}
	}
	
	/**
	 * 获取 TriggerKey 
	 * @param jobId 需要唯一
	 * @return
	 */
	public static TriggerKey getTriggerKey(Long jobId) {
		return TriggerKey.triggerKey(JOB_NAME + jobId);
	}
	
	/**
	 * 获取JobKey
	 * @param jobId 需要唯一
	 * @return
	 */
	public static JobKey getJobKey(Long jobId) {
		return JobKey.jobKey(JOB_NAME + jobId);
	}
	
	/**
	 * 获取className的Class对象
	 * @param className
	 * @return
	 */
	public static Class<?> getScheduleJobClass(String className) {
		try {
			return Class.forName(className);
		} catch (ClassNotFoundException e) {
			return null;
		}
	}
	
	/**
	 * 判断Job Class 是否有实现CronJob 接口
	 * @param type
	 * @return
	 */
	public static boolean isCronJob(Class<?> type) {
		Class<?>[] interfaces = type.getInterfaces();
		for(Class<?> inter : interfaces) {
			if(inter == CronJob.class) {
				return true;
			}
		}
		return false;
	}
	
}
